package com.cyzy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cyzy.dto.BalancePayDto;
import com.cyzy.dto.MyAllAdoptOrderDto;
import com.cyzy.dto.OrderCreateDto;
import com.cyzy.mapper.AdoptMapper;
import com.cyzy.mapper.OrderMapper;
import com.cyzy.mapper.OrdersMapper;
import com.cyzy.mapper.PaymentMapper;
import com.cyzy.mapper.UserMapper;
import com.cyzy.pojo.Adopt;
import com.cyzy.pojo.Orders;
import com.cyzy.pojo.Payment;
import com.cyzy.pojo.User;
import com.cyzy.service.DistributedLockService;
import com.cyzy.service.OrderService;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private OrdersMapper ordersMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private PaymentMapper paymentMapper;
    
    @Autowired
    private AdoptMapper adoptMapper;
    
    @Autowired
    private DistributedLockService distributedLockService;
    
    @Override
    public Orders createOrder(OrderCreateDto orderCreateDto) {
        // 检查订单号是否已存在
        QueryWrapper<Orders> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_num", orderCreateDto.getOrder_num());
        Orders existingOrder = orderMapper.selectOne(queryWrapper);
        
        if (existingOrder != null) {
            // 订单号已存在，直接返回已存在的订单
            log.info("订单号已存在，直接返回: {}", orderCreateDto.getOrder_num());
            return existingOrder;
        }
        
        // 使用分布式锁防止超买超卖
        String lockKey = "adopt:order:create:" + orderCreateDto.getRelated_id();
        return distributedLockService.executeWithLock(lockKey, () -> {
            return createOrderWithLock(orderCreateDto);
        });
    }
    
    /**
     * 在分布式锁保护下创建订单
     */
    @Transactional(rollbackFor = Exception.class)
    private Orders createOrderWithLock(OrderCreateDto orderCreateDto) {
        log.info("开始创建订单，认养商品ID: {}, 购买数量: {}", 
                orderCreateDto.getRelated_id(), orderCreateDto.getOrder_quantity());
        
        // 使用悲观锁查询认养商品信息，防止并发修改
        Adopt adopt = adoptMapper.selectByIdForUpdate(orderCreateDto.getRelated_id());
        if (adopt == null) {
            throw new RuntimeException("认养商品不存在");
        }
        
        // 计算已售数量（所有有效订单中order_quantity的总和）
        QueryWrapper<Orders> orderQuery = new QueryWrapper<>();
        orderQuery.select("IFNULL(SUM(order_quantity), 0) as total_sold")
                 .eq("related_id", orderCreateDto.getRelated_id())
                 .eq("order_type", "认养")
                 .in("order_status", 1, 2); // 1:已支付, 2:待支付
        
        List<Map<String, Object>> result = orderMapper.selectMaps(orderQuery);
        Integer soldCount = 0;
        if (!result.isEmpty() && result.get(0).get("total_sold") != null) {
            soldCount = Integer.valueOf(result.get(0).get("total_sold").toString());
        }
        
        // 计算可用库存
        int availableStock = (int) adopt.getAdoptStock() - soldCount;
        
        log.info("库存检查 - 总库存: {}, 已售数量: {}, 可用库存: {}, 购买数量: {}", 
                adopt.getAdoptStock(), soldCount, availableStock, orderCreateDto.getOrder_quantity());
        
        // 检查库存是否足够
        if (availableStock < orderCreateDto.getOrder_quantity()) {
            log.warn("库存不足 - 可用库存: {}, 购买数量: {}", availableStock, orderCreateDto.getOrder_quantity());
            throw new RuntimeException("库存不足，当前可用库存：" + availableStock + "，购买数量：" + orderCreateDto.getOrder_quantity());
        }
        
        // 创建订单对象
        Orders order = new Orders();
        
        // 设置订单基本信息
        order.setOrderNum(orderCreateDto.getOrder_num());
        order.setUserId(orderCreateDto.getUser_id());
        order.setOrderType(orderCreateDto.getOrder_type());
        order.setRelatedId(orderCreateDto.getRelated_id());
        order.setOrderAmount(orderCreateDto.getOrder_amount());
        order.setLeastTime(orderCreateDto.getLeast_time());
        order.setOrderAddressId(orderCreateDto.getOrder_address_id());
        order.setOrderQuantity(orderCreateDto.getOrder_quantity());
        
        // 设置订单状态为待支付（2）
        order.setOrderStatus(2L);
        order.setPayTime(null);
        
        // 插入数据库
        int insertResult = orderMapper.insert(order);
        if (insertResult == 0) {
            log.error("订单插入失败: {}", orderCreateDto.getOrder_num());
            throw new RuntimeException("订单创建失败");
        }
        
        log.info("订单创建成功 - 订单号: {}, 订单ID: {}", order.getOrderNum(), order.getOrderId());
        return order;
    }
    
    @Override
    public String balancePay(BalancePayDto balancePayDto) {
        // 使用分布式锁保护支付过程
        String lockKey = "adopt:payment:" + balancePayDto.getOrder_num();
        return distributedLockService.executeWithLock(lockKey, () -> {
            return balancePayWithLock(balancePayDto);
        });
    }
    
    /**
     * 在分布式锁保护下进行余额支付
     */
    @Transactional(rollbackFor = Exception.class)
    private String balancePayWithLock(BalancePayDto balancePayDto) {
        log.info("开始余额支付，订单号: {}, 支付金额: {}", balancePayDto.getOrder_num(), balancePayDto.getOrder_amount());
        // 1. 查询用户信息
        User user = userMapper.selectById(balancePayDto.getUser_id());
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 2. 验证支付密码
        if (balancePayDto.getPayment_password() == null || balancePayDto.getPayment_password().trim().isEmpty()) {
            throw new RuntimeException("请输入支付密码");
        }
        
        // 对前端传来的支付密码进行MD5加密
        String encryptedPassword = DigestUtils.md5DigestAsHex(balancePayDto.getPayment_password().getBytes());
        
        // 验证支付密码是否正确
        if (user.getUserPayPwd() == null || !user.getUserPayPwd().equals(encryptedPassword)) {
            throw new RuntimeException("支付密码错误");
        }
        
        // 3. 检查用户余额是否足够
        if (user.getUserMoney() < balancePayDto.getOrder_amount()) {
            throw new RuntimeException("用户余额不足，当前余额：" + user.getUserMoney() + "元");
        }
        
        // 4. 查询订单信息
        QueryWrapper<Orders> orderQuery = new QueryWrapper<>();
        orderQuery.eq("order_num", balancePayDto.getOrder_num());
        Orders order = orderMapper.selectOne(orderQuery);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        
        // 5. 检查订单状态是否为待支付
        if (order.getOrderStatus() != 2L) {
            throw new RuntimeException("订单状态异常，无法支付");
        }
        
        // 6. 如果是认养订单，需要再次检查库存（防止支付时库存不足）
        if ("认养".equals(order.getOrderType())) {
            Adopt adopt = adoptMapper.selectByIdForUpdate(order.getRelatedId());
            if (adopt == null) {
                throw new RuntimeException("认养商品不存在");
            }
            
            // 重新计算已售数量（排除当前订单）
            QueryWrapper<Orders> stockQuery = new QueryWrapper<>();
            stockQuery.select("IFNULL(SUM(order_quantity), 0) as total_sold")
                     .eq("related_id", order.getRelatedId())
                     .eq("order_type", "认养")
                     .eq("order_status", 1) // 只计算已支付的订单
                     .ne("order_id", order.getOrderId()); // 排除当前订单
            
            List<Map<String, Object>> stockResult = orderMapper.selectMaps(stockQuery);
            Integer paidSoldCount = 0;
            if (!stockResult.isEmpty() && stockResult.get(0).get("total_sold") != null) {
                paidSoldCount = Integer.valueOf(stockResult.get(0).get("total_sold").toString());
            }
            
            // 计算支付后的可用库存
            int availableAfterPay = (int) adopt.getAdoptStock() - paidSoldCount - order.getOrderQuantity();
            
            log.info("支付时库存检查 - 总库存: {}, 已支付数量: {}, 当前订单数量: {}, 支付后可用库存: {}", 
                    adopt.getAdoptStock(), paidSoldCount, order.getOrderQuantity(), availableAfterPay);
            
            if (availableAfterPay < 0) {
                log.warn("支付时库存不足 - 支付后可用库存: {}", availableAfterPay);
                throw new RuntimeException("库存不足，支付失败");
            }
        }
        
        // 7. 扣减用户余额
        double newBalance = user.getUserMoney() - balancePayDto.getOrder_amount();
        UpdateWrapper<User> userUpdate = new UpdateWrapper<>();
        userUpdate.eq("user_id", balancePayDto.getUser_id());
        userUpdate.set("user_money", newBalance);
        int userUpdateResult = userMapper.update(null, userUpdate);
        if (userUpdateResult == 0) {
            throw new RuntimeException("用户余额更新失败");
        }
        
        // 8. 更新订单状态为已支付（1）和支付时间
        UpdateWrapper<Orders> orderUpdate = new UpdateWrapper<>();
        orderUpdate.eq("order_num", balancePayDto.getOrder_num());
        orderUpdate.set("order_status", 1);
        orderUpdate.set("pay_time", Timestamp.valueOf(LocalDateTime.now()));
        int orderUpdateResult = orderMapper.update(null, orderUpdate);
        if (orderUpdateResult == 0) {
            throw new RuntimeException("订单状态更新失败");
        }
        
        // 9. 插入支付记录到payment表
        Payment payment = new Payment();
        payment.setOrderId(order.getOrderId());
        payment.setPaymentMethod("余额支付");
        payment.setTransactionId(balancePayDto.getOrder_num());
        payment.setAmount(balancePayDto.getOrder_amount());
        payment.setStatus(1L);
        // payTime、createdAt、updatedAt由数据库自动设置
        
        int paymentInsertResult = paymentMapper.insert(payment);
        if (paymentInsertResult == 0) {
            throw new RuntimeException("支付记录插入失败");
        }
        
        log.info("余额支付成功 - 订单号: {}, 用户ID: {}, 金额: {}", 
                balancePayDto.getOrder_num(), balancePayDto.getUser_id(), balancePayDto.getOrder_amount());
        return "支付成功";
    }
    
    @Override
    public List<MyAllAdoptOrderDto> getUserAdoptOrders(Long userId) {
        // 使用MPJLambdaWrapper进行连表查询
        MPJLambdaWrapper<Orders> wrapper = new MPJLambdaWrapper<Orders>()
                .selectAs(Orders::getOrderId, MyAllAdoptOrderDto::getOrderId)
                .selectAs(Orders::getOrderAmount, MyAllAdoptOrderDto::getOrderAmount)
                .selectAs(Orders::getLeastTime, MyAllAdoptOrderDto::getLeastTime)
                .selectAs(Orders::getOrderQuantity, MyAllAdoptOrderDto::getOrderQuantity)
                .selectAs(Adopt::getAdoptName, MyAllAdoptOrderDto::getAdoptName)
                .selectAs(Orders::getOrderStatus, MyAllAdoptOrderDto::getOrderStatus)
                .leftJoin(Adopt.class, Adopt::getAdoptId, Orders::getRelatedId)
                .eq(Orders::getUserId, userId)
                .eq(Orders::getOrderType, "认养")
                .in(Orders::getOrderStatus, 0, 1, 2); // 1已付款，2待付款
        
        return ordersMapper.selectJoinList(MyAllAdoptOrderDto.class, wrapper);
    }
    
    @Override
    public List<MyAllAdoptOrderDto> getUserActiveAdoptOrders(Long userId) {
        // 使用MPJLambdaWrapper进行连表查询 - 认养中的订单（已付款且租赁期内）
        MPJLambdaWrapper<Orders> wrapper = new MPJLambdaWrapper<Orders>()
                .selectAs(Orders::getOrderId, MyAllAdoptOrderDto::getOrderId)
                .selectAs(Orders::getOrderAmount, MyAllAdoptOrderDto::getOrderAmount)
                .select("CAST(DATEDIFF(DATE_ADD(t.pay_time, INTERVAL t.least_time DAY), NOW()) AS SIGNED) AS leastTime") // 计算剩余天数，确保返回整数
                .selectAs(Orders::getOrderQuantity, MyAllAdoptOrderDto::getOrderQuantity)
                .selectAs(Adopt::getAdoptName, MyAllAdoptOrderDto::getAdoptName)
                .selectAs(Orders::getOrderStatus, MyAllAdoptOrderDto::getOrderStatus)
                .leftJoin(Adopt.class, Adopt::getAdoptId, Orders::getRelatedId)
                .eq(Orders::getUserId, userId)
                .eq(Orders::getOrderType, "认养")
                .eq(Orders::getOrderStatus, 1) // 已付款
                .isNotNull(Orders::getPayTime) // 支付时间不为空
                .apply("DATE_ADD(pay_time, INTERVAL least_time DAY) > NOW()"); // 租赁期未结束
        
        return ordersMapper.selectJoinList(MyAllAdoptOrderDto.class, wrapper);
    }
    
    @Override
    public List<MyAllAdoptOrderDto> getUserCompletedAdoptOrders(Long userId) {
        // 使用MPJLambdaWrapper进行连表查询 - 已完成的订单（已付款且租赁期已结束）
        MPJLambdaWrapper<Orders> wrapper = new MPJLambdaWrapper<Orders>()
                .selectAs(Orders::getOrderId, MyAllAdoptOrderDto::getOrderId)
                .selectAs(Orders::getOrderAmount, MyAllAdoptOrderDto::getOrderAmount)
                .selectAs(Orders::getLeastTime, MyAllAdoptOrderDto::getLeastTime)
                .selectAs(Orders::getOrderQuantity, MyAllAdoptOrderDto::getOrderQuantity)
                .selectAs(Adopt::getAdoptName, MyAllAdoptOrderDto::getAdoptName)
                .selectAs(Orders::getOrderStatus, MyAllAdoptOrderDto::getOrderStatus)
                .leftJoin(Adopt.class, Adopt::getAdoptId, Orders::getRelatedId)
                .eq(Orders::getUserId, userId)
                .eq(Orders::getOrderType, "认养")
                .eq(Orders::getOrderStatus, 1) // 已付款
                .isNotNull(Orders::getPayTime) // 支付时间不为空
                .apply("DATE_ADD(pay_time, INTERVAL least_time DAY) <= NOW()"); // 租赁期已结束
        
        return ordersMapper.selectJoinList(MyAllAdoptOrderDto.class, wrapper);
    }
    
    @Override
    public List<MyAllAdoptOrderDto> getUserUnpaidAdoptOrders(Long userId) {
        // 使用MPJLambdaWrapper进行连表查询 - 待支付订单（状态为2）
        MPJLambdaWrapper<Orders> wrapper = new MPJLambdaWrapper<Orders>()
                .selectAs(Orders::getOrderId, MyAllAdoptOrderDto::getOrderId)
                .selectAs(Orders::getOrderAmount, MyAllAdoptOrderDto::getOrderAmount)
                .selectAs(Orders::getLeastTime, MyAllAdoptOrderDto::getLeastTime)
                .selectAs(Orders::getOrderQuantity, MyAllAdoptOrderDto::getOrderQuantity)
                .selectAs(Adopt::getAdoptName, MyAllAdoptOrderDto::getAdoptName)
                .selectAs(Orders::getOrderStatus, MyAllAdoptOrderDto::getOrderStatus)
                .leftJoin(Adopt.class, Adopt::getAdoptId, Orders::getRelatedId)
                .eq(Orders::getUserId, userId)
                .eq(Orders::getOrderType, "认养")
                .eq(Orders::getOrderStatus, 2); // 待支付
        
        return ordersMapper.selectJoinList(MyAllAdoptOrderDto.class, wrapper);
    }
    
    @Override
    @Transactional
    public Boolean deleteOrder(Long orderId) {
        // 检查订单是否存在
        Orders order = orderMapper.selectById(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        
        // 更新订单状态为10（假删除）
        UpdateWrapper<Orders> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("order_id", orderId);
        updateWrapper.set("order_status", 10);
        
        int updateResult = orderMapper.update(null, updateWrapper);
        return updateResult > 0;
    }
    
    @Override
    @Transactional
    public Boolean cancelOrder(Long orderId) {
        // 检查订单是否存在
        Orders order = orderMapper.selectById(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        
        // 检查订单状态是否可以取消（只有待支付的订单可以取消）
        if (order.getOrderStatus() != 2) {
            throw new RuntimeException("只有待支付的订单才能取消");
        }
        
        // 更新订单状态为0（已取消）
        UpdateWrapper<Orders> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("order_id", orderId);
        updateWrapper.set("order_status", 0);
        
        int updateResult = orderMapper.update(null, updateWrapper);
        return updateResult > 0;
    }
} 